Remove exception WRT same-crate non_exhaustive reads#2162
Conversation
When matching against a single-variant enum marked `non_exhaustive` and defined in a different crate, we pretend that there might be multiple variants and force a read of the discriminant. In [Rust PR 150681], we decided to remove the same-crate exception. Now matching against a single-variant `non_exhaustive` enum in the same crate will also cause a discriminant read. Separately, prior to [Rust PR 150681], `rustc` was eliding the discriminant read when an enum has only one *inhabited* variant. This contradicts what the Reference says in: > r[type.closure.capture.precision.discriminants.uninhabited-variants] > > Even if all variants but the one being matched against are > uninhabited, making the pattern [irrefutable][patterns.refutable], > the discriminant is still read if it otherwise would be. We decided with our lang FCP to confirm the behavior already encoded in the Reference, so no change is needed there. [Rust PR 150681]: rust-lang/rust#150681
| If [`#[non_exhaustive]`][attributes.type-system.non_exhaustive] is applied to an enum, the enum is treated as having multiple variants for the purpose of deciding whether a read occurs, even if it actually has only one variant. | ||
|
|
||
| r[type.closure.capture.precision.discriminants.uninhabited-variants] | ||
| Even if all variants but the one being matched against are uninhabited, making the pattern [irrefutable][patterns.refutable], the discriminant is still read if it otherwise would be. |
There was a problem hiding this comment.
While we're at it, I feel like the "if it otherwise would be" here can be kind of confusing... do you have any ideas on how to rephrase this? Maybe this would be an improvement?
| Even if all variants but the one being matched against are uninhabited, making the pattern [irrefutable][patterns.refutable], the discriminant is still read if it otherwise would be. | |
| Even if all variants but the one being matched against are uninhabited, making the pattern [irrefutable][patterns.refutable], the discriminant is still read when it otherwise would be. |
|
Regardless of my comment above, I do agree that this PR is enough to document the changes being done by #150681... apart from the subtlety that the change doesn't only affect closure captures. Indeed, this whole section on discriminant reads should probably be moved out of the section on closures entirely – but that's a bigger refactor that can probably be done later (especially since we'd probably end up trying to document more of the runtime semantics of patterns). (and yeah, I do realize that I was the one who put this text in that part of the reference in the first place, but in my defense, at the time I was only making compiler changes to the closure capture rules specifically 😅) |
ehuss
left a comment
There was a problem hiding this comment.
Thanks! Merging now that rust-lang/rust#150681 has merged.
Update books ## rust-embedded/book 1 commits in fe88fbb68391a465680dd91109f0a151a1676f3e..99d0341ff4e06757490af8fceee790c4ede50bc0 2026-02-11 12:58:13 UTC to 2026-02-11 12:58:13 UTC - Remove triagebot.toml (rust-embedded/book#405) ## rust-lang/reference 21 commits in addd0602c819b6526b9cc97653b0fadca395528c..442cbef9105662887d5eae2882ca551f3726bf28 2026-02-22 02:55:12 UTC to 2026-02-11 01:41:05 UTC - Document importing path-segment keyword (rust-lang/reference#2136) - avoid needless dereference (rust-lang/reference#2180) - Use `clobber_abi`s corresponding to the called functions in `[asm.abi-clobbers.many]`'s example. (rust-lang/reference#2170) - expr.paren.evaluation: fix and make more simple (rust-lang/reference#2158) - const-eval.const-context.outer-generics: make more clear/obvious (rust-lang/reference#2159) - Nightly test links: update rust branch name (use `main`) (rust-lang/reference#2185) - tools/xtask: update rust branch name for linkcheck script (use `main`) (rust-lang/reference#2184) - specify `if let` guards with updated scoping rules (rust-lang/reference#1957) - Document assignment expression as coercion site (rust-lang/reference#1954) - Remove exception WRT same-crate `non_exhaustive` reads (rust-lang/reference#2162) - Add negative lookahead (rust-lang/reference#2172) - Switch to new range syntax (rust-lang/reference#2173) - add mdbook output for dev-guide to ignore file (rust-lang/reference#2178) - Fix rule name for while syntax (rust-lang/reference#2175) - block-expr: add new rule expr.block.result-value (rust-lang/reference#2174) - lifetime-elision.md: add some missing periods (rust-lang/reference#2176) - Add cut operator (`^`) to grammar (rust-lang/reference#2104) - dev-guide stabilization.md: add missing "not" (rust-lang/reference#2167) - Add method call and await expr for Dot in syntax index (rust-lang/reference#2163) - Fix sort of punctuation list (rust-lang/reference#2161) - Add a contributor guide (rust-lang/reference#2097) ## rust-lang/rust-by-example 1 commits in bac931ef1673af63fb60c3d691633034713cca20..5383db524711c0c9c43c3ca9e5e706089672ed6a 2026-02-16 12:02:33 UTC to 2026-02-16 12:02:33 UTC - 1.2.2 Display: Fix typo in bonus instructions (before -> after) (rust-lang/rust-by-example#1998)
Update books ## rust-embedded/book 1 commits in fe88fbb68391a465680dd91109f0a151a1676f3e..99d0341ff4e06757490af8fceee790c4ede50bc0 2026-02-11 12:58:13 UTC to 2026-02-11 12:58:13 UTC - Remove triagebot.toml (rust-embedded/book#405) ## rust-lang/reference 21 commits in addd0602c819b6526b9cc97653b0fadca395528c..442cbef9105662887d5eae2882ca551f3726bf28 2026-02-22 02:55:12 UTC to 2026-02-11 01:41:05 UTC - Document importing path-segment keyword (rust-lang/reference#2136) - avoid needless dereference (rust-lang/reference#2180) - Use `clobber_abi`s corresponding to the called functions in `[asm.abi-clobbers.many]`'s example. (rust-lang/reference#2170) - expr.paren.evaluation: fix and make more simple (rust-lang/reference#2158) - const-eval.const-context.outer-generics: make more clear/obvious (rust-lang/reference#2159) - Nightly test links: update rust branch name (use `main`) (rust-lang/reference#2185) - tools/xtask: update rust branch name for linkcheck script (use `main`) (rust-lang/reference#2184) - specify `if let` guards with updated scoping rules (rust-lang/reference#1957) - Document assignment expression as coercion site (rust-lang/reference#1954) - Remove exception WRT same-crate `non_exhaustive` reads (rust-lang/reference#2162) - Add negative lookahead (rust-lang/reference#2172) - Switch to new range syntax (rust-lang/reference#2173) - add mdbook output for dev-guide to ignore file (rust-lang/reference#2178) - Fix rule name for while syntax (rust-lang/reference#2175) - block-expr: add new rule expr.block.result-value (rust-lang/reference#2174) - lifetime-elision.md: add some missing periods (rust-lang/reference#2176) - Add cut operator (`^`) to grammar (rust-lang/reference#2104) - dev-guide stabilization.md: add missing "not" (rust-lang/reference#2167) - Add method call and await expr for Dot in syntax index (rust-lang/reference#2163) - Fix sort of punctuation list (rust-lang/reference#2161) - Add a contributor guide (rust-lang/reference#2097) ## rust-lang/rust-by-example 1 commits in bac931ef1673af63fb60c3d691633034713cca20..5383db524711c0c9c43c3ca9e5e706089672ed6a 2026-02-16 12:02:33 UTC to 2026-02-16 12:02:33 UTC - 1.2.2 Display: Fix typo in bonus instructions (before -> after) (rust-lang/rust-by-example#1998)
Update books ## rust-embedded/book 1 commits in fe88fbb68391a465680dd91109f0a151a1676f3e..99d0341ff4e06757490af8fceee790c4ede50bc0 2026-02-11 12:58:13 UTC to 2026-02-11 12:58:13 UTC - Remove triagebot.toml (rust-embedded/book#405) ## rust-lang/reference 21 commits in addd0602c819b6526b9cc97653b0fadca395528c..442cbef9105662887d5eae2882ca551f3726bf28 2026-02-22 02:55:12 UTC to 2026-02-11 01:41:05 UTC - Document importing path-segment keyword (rust-lang/reference#2136) - avoid needless dereference (rust-lang/reference#2180) - Use `clobber_abi`s corresponding to the called functions in `[asm.abi-clobbers.many]`'s example. (rust-lang/reference#2170) - expr.paren.evaluation: fix and make more simple (rust-lang/reference#2158) - const-eval.const-context.outer-generics: make more clear/obvious (rust-lang/reference#2159) - Nightly test links: update rust branch name (use `main`) (rust-lang/reference#2185) - tools/xtask: update rust branch name for linkcheck script (use `main`) (rust-lang/reference#2184) - specify `if let` guards with updated scoping rules (rust-lang/reference#1957) - Document assignment expression as coercion site (rust-lang/reference#1954) - Remove exception WRT same-crate `non_exhaustive` reads (rust-lang/reference#2162) - Add negative lookahead (rust-lang/reference#2172) - Switch to new range syntax (rust-lang/reference#2173) - add mdbook output for dev-guide to ignore file (rust-lang/reference#2178) - Fix rule name for while syntax (rust-lang/reference#2175) - block-expr: add new rule expr.block.result-value (rust-lang/reference#2174) - lifetime-elision.md: add some missing periods (rust-lang/reference#2176) - Add cut operator (`^`) to grammar (rust-lang/reference#2104) - dev-guide stabilization.md: add missing "not" (rust-lang/reference#2167) - Add method call and await expr for Dot in syntax index (rust-lang/reference#2163) - Fix sort of punctuation list (rust-lang/reference#2161) - Add a contributor guide (rust-lang/reference#2097) ## rust-lang/rust-by-example 1 commits in bac931ef1673af63fb60c3d691633034713cca20..5383db524711c0c9c43c3ca9e5e706089672ed6a 2026-02-16 12:02:33 UTC to 2026-02-16 12:02:33 UTC - 1.2.2 Display: Fix typo in bonus instructions (before -> after) (rust-lang/rust-by-example#1998)
Rollup merge of #153023 - rustbot:docs-update, r=ehuss Update books ## rust-embedded/book 1 commits in fe88fbb68391a465680dd91109f0a151a1676f3e..99d0341ff4e06757490af8fceee790c4ede50bc0 2026-02-11 12:58:13 UTC to 2026-02-11 12:58:13 UTC - Remove triagebot.toml (rust-embedded/book#405) ## rust-lang/reference 21 commits in addd0602c819b6526b9cc97653b0fadca395528c..442cbef9105662887d5eae2882ca551f3726bf28 2026-02-22 02:55:12 UTC to 2026-02-11 01:41:05 UTC - Document importing path-segment keyword (rust-lang/reference#2136) - avoid needless dereference (rust-lang/reference#2180) - Use `clobber_abi`s corresponding to the called functions in `[asm.abi-clobbers.many]`'s example. (rust-lang/reference#2170) - expr.paren.evaluation: fix and make more simple (rust-lang/reference#2158) - const-eval.const-context.outer-generics: make more clear/obvious (rust-lang/reference#2159) - Nightly test links: update rust branch name (use `main`) (rust-lang/reference#2185) - tools/xtask: update rust branch name for linkcheck script (use `main`) (rust-lang/reference#2184) - specify `if let` guards with updated scoping rules (rust-lang/reference#1957) - Document assignment expression as coercion site (rust-lang/reference#1954) - Remove exception WRT same-crate `non_exhaustive` reads (rust-lang/reference#2162) - Add negative lookahead (rust-lang/reference#2172) - Switch to new range syntax (rust-lang/reference#2173) - add mdbook output for dev-guide to ignore file (rust-lang/reference#2178) - Fix rule name for while syntax (rust-lang/reference#2175) - block-expr: add new rule expr.block.result-value (rust-lang/reference#2174) - lifetime-elision.md: add some missing periods (rust-lang/reference#2176) - Add cut operator (`^`) to grammar (rust-lang/reference#2104) - dev-guide stabilization.md: add missing "not" (rust-lang/reference#2167) - Add method call and await expr for Dot in syntax index (rust-lang/reference#2163) - Fix sort of punctuation list (rust-lang/reference#2161) - Add a contributor guide (rust-lang/reference#2097) ## rust-lang/rust-by-example 1 commits in bac931ef1673af63fb60c3d691633034713cca20..5383db524711c0c9c43c3ca9e5e706089672ed6a 2026-02-16 12:02:33 UTC to 2026-02-16 12:02:33 UTC - 1.2.2 Display: Fix typo in bonus instructions (before -> after) (rust-lang/rust-by-example#1998)
Stabilization:
When matching against a single-variant enum marked
non_exhaustiveand defined in a different crate, we pretend that there might be multiple variants and force a read of the discriminant. In Rust PR 150681, we decided to remove the same-crate exception. Now matching against a single-variantnon_exhaustiveenum in the same crate will also cause a discriminant read.Separately, prior to Rust PR 150681,
rustcwas eliding the discriminant read when an enum has only one inhabited variant. This contradicts what the Reference says in:We decided with our lang FCP to confirm the behavior already encoded in the Reference, so no change is needed there.
cc @meithecatte @ehuss